package stockblaster.client;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;

import stockblaster.client.facilities.Facilities;
import stockblaster.client.objectives.MoneyObjective;
import stockblaster.client.objectives.Objective;
import android.app.Activity;

public class CurrentUser {
	private static String[] help;
	private static String[] objectives;
	private static int helpNum = 0;
	
	public static int currentMainTab = 1;
	public static int currentCompanyStockInfoTab = 1;
	
	public static int OBJECTIVE = 1;
	public static int HELP = 2;
	public static int COMPANY_INFO = 3;
	
	public static boolean firstFourTriggered = false; //TODO set to StockUser class
			
	public static HashMap<Integer, HashMap<String, Double>> gainLoss; //TODO set to StockUser class
	
	private static Class<?> from_company_info = null;
	private static Class<?> from_objective = null;
	private static Class<?> from_help = null;
	public static Class<?> current_class = null;
	private static String username = "";
	private static Double fund = 0.00;
	public static Objective currentObj;
	
	private static String companySearchPick = "";
	
	private static int month = 1;
	public static int year = 2011;
	
	public static ArrayList<Objective> objectiveList = new ArrayList<Objective>();
	public static int objectiveNumber = 1;
	
	//<CompanyName, number of shares user owns in that company>
	private static HashMap<String, Integer> shares =
			new HashMap<String, Integer>();
	
	//LinkedList as container for company names whose part of the shares
	//  are owned by user
	private static LinkedList<String> companyNames = new LinkedList<String>();
	
	
	/**
	 * Method to set current user
	 * @param uName username
	 */
	public static void setCurrentUser(String uName) {
		currentObj = new MoneyObjective(ObjectiveText.objectiveArdo[6],
				Objective.MONEY_OBJECTIVE, 25500);
		username = uName;
		shares = Users.users.get(uName).getShares();
		companyNames = Users.users.get(uName).getCompanyNames();
		fund = Users.users.get(uName).getFund();
		help = Users.users.get(uName).getHelp();
		objectives = Users.users.get(uName).getObjectives();
		helpNum = Users.users.get(uName).getHelpNum();
		gainLoss = new HashMap<Integer, HashMap<String, Double>>();
	}
	
	/**
	 * Method to check whether the objective has been completed
	 * @param a activity user is currently on
	 * @return true if it's completed, false otherwise
	 */
	public static boolean checkObjective(Activity a) {
		if (!CurrentUser.currentObj.isCompleted()) {
        	if (CurrentUser.currentObj.check()) {
        		CurrentUser.currentObj.complete();
        		int moneyGoal = currentObj.getMoneyGoal();
        		takeObjectiveBasedMoney();
        		addFacility();
        		updateObjective();
        		int num = CurrentUser.objectiveNumber - 1;
        		MethodHelper.showAlertBox(a,
        				"Objective " + num + " completed!",
        				MethodHelper.twoDecimal(moneyGoal) + " has been taken away from your funds" + "\n" +
        				"Next objective: " + CurrentUser.currentObj.getObjective());
        		return true;
        	}
        }
		return false;
	}
	
	/**
	 * Method to update the objective
	 */
	public static void updateObjective() {
		objectiveNumber++;
		if (objectiveNumber > 7)
			return;
		CurrentUser.currentObj = objectiveList.get(objectiveNumber - 1);
	}
	
	private static void addFacility() {
		switch (objectiveNumber) {
		case 1:
			Facilities.addFacility(Facilities.FACILITY_DEBT);
			break;
		case 2:
			Facilities.addFacility(Facilities.FACILITY_IMPROVED_FOOD);
			break;
		case 3:
			Facilities.addFacility(Facilities.FACILITY_RENOVATED_ROOMS);
			break;
		case 4:
			Facilities.addFacility(Facilities.FACILITY_IMPROVED_STAFF);
			break;
		case 5:
			Facilities.addFacility(Facilities.FACILITY_BALLROOM);
			break;
		case 6:
			Facilities.addFacility(Facilities.FACILITY_SWIMMING_POOL);
			break;
		case 7:
			Facilities.addFacility(Facilities.FACILITY_SPA_GYM);
			break;
		}
	}
	
	private static void takeObjectiveBasedMoney() {
		switch (objectiveNumber) {
		case 1:
		case 2:
		case 3:
			CurrentUser.takeFund(Double.
					parseDouble(currentObj.getMoneyGoal().toString()));
			break;
		case 4:
			//Facilities.addFacility(Facilities.FACILITY_IMPROVED_STAFF);
			break;
		case 5:
		case 6:
		case 7:
			CurrentUser.takeFund(Double.
					parseDouble(currentObj.getMoneyGoal().toString()));
			break;
		}
	}
	
	/**
	 * Method to get the current class user is on
	 * @return the class String representative
	 */
	public static String getCurrentClass() {
		return current_class.getClass().getName();
	}
	
	/**
	 * Method to get the tab user is on on the main screen
	 * @return the position of the tab, [1, 4]; 0 if user is not on the main screen
	 */
	public static int getCurrentMainTab() {
		if (!CurrentUser.current_class.equals(MainPageActivity.class)) {
			return 0;
		}
		return CurrentUser.currentMainTab;
	}
	
	/**
	 * Method to get the tab user is on on the company info screen
	 * @return the position of the tab [1, 3]; 0 if user is not on the company info screen
	 */
	public static int getCurrentCompanyTab() {
		if (!CurrentUser.current_class.equals(CompanyStockInfoActivity.class)) {
			return 0;
		}
		return CurrentUser.currentCompanyStockInfoTab;
	}
	
	/**
	 * Method to update the gain loss for each company based on our share value
	 * @param month the month to be stored
	 * @param cName the company name
	 * @param value the value of the share of the month
	 */
	public static void updateGainLoss(Integer month, String cName, Double value) {
		if (gainLoss.containsKey(month)) {
			HashMap<String, Double> mapTemp = gainLoss.get(month);
			mapTemp.put(cName, value);
			gainLoss.put(month, mapTemp);
		} else {
			HashMap<String, Double> mapTemp = new HashMap<String, Double>();
			mapTemp.put(cName, value);
			gainLoss.put(month, mapTemp);
		}
		//TODO need to add to StockUser
	}
	
	/**
	 * Method to add the month
	 */
	public static void addMonth() {
		++month;
		if (month > 12) {
			resetMonth();
			addYear(); //TODO apply this to stockuser
		}
		Facilities.addMonthlyIncome();
		Users.users.get(username).addMonth();
	}
	
	/**
	 * Getter method for month
	 * @return month
	 */
	public static int getMonth() {
		return month;
	}
	
	/**
	 * Method to reset the month
	 */
	public static void resetMonth() {
		month = 1;
		Users.users.get(username).resetMonth();
	}
	
	/**
	 * Method to add year
	 */
	public static void addYear() {
		year++; //TODO add to stockuser
	}
	
	/**
	 * Getter method for year
	 * @return year
	 */
	public static int getYear() {
		return year; //TODO add to stockuser
	}
	
	public static void setFirstFourTriggered(boolean _b) {
		firstFourTriggered = _b;
		Users.users.get(username).setFirstFourTriggered(_b);
	}
	
	/**
	 * Method to get help text
	 * @param i the help number
	 * @return user's help
	 */
	public static String getHelp(int i) {
		return help[i];
	}
	
	public static String getObjectives(int i) {
		return objectives[i];
	}
	
	/**
	 * Method to increase the helpNum
	 */
	public static void addHelpNum() {
		++helpNum;
		Users.users.get(username).addHelpNum();
	}
	
	/**
	 * Method to get the help num
	 * @return the help number
	 */
	public static int getHelpNum() {
		return helpNum;
	}
	
	/**
	 * Method to create new user
	 * @param _uName username
	 * @param _fund starting fund
	 */
	public static void createNewUser(String _uName, Double _fund) {
		Users.users.put(_uName, new StockUser(_uName, "", _fund));
		try {
			Thread.sleep(50);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		setCurrentUser(_uName);
	}
	
	/**
	 * Method to set the company that user picks from Search view
	 * @param cName the company name
	 */
	public static void setCompanyPick(String cName) {
		companySearchPick = cName;
	}
	
	/**
	 * Method to get the company that user pickes from Search view
	 * @return the company name
	 */
	public static String getCompanyPick() {
		return companySearchPick;
	}
	
	/**
	 * Method to set where the user is from before going to an activity
	 * @param _from the class where the user is from
	 */
	public static void setFromClass(Class<?> _from, int whichOne) {
		if (whichOne == OBJECTIVE) { 
			from_objective = _from;
		} else if (whichOne == HELP) {
			from_help = _from;
		} else if (whichOne == COMPANY_INFO) {
			from_company_info = _from;
		}
	}
	
	/**
	 * Method to get the class where user is from
	 * @return the class where the user is from;
	 */
	public static Class<?> getFromClass(int whichOne) {
		if (whichOne == OBJECTIVE) { 
			return from_objective;
		} else if (whichOne == HELP) {
			return from_help;
		} else if (whichOne == COMPANY_INFO) {
			return from_company_info;
		}
		
		//this is to prevent crash
		return MainPageActivity.class;
	}
	
	/**
	 * Method to get username
	 * @return username
	 */
	public static String getUsername() {
		return username;
	}
	
	/**
	 * Method to get user's fund (cash)
	 * @return Double value of user's fund
	 */
	public static Double getFund() {
		return fund;
	}
	
	/**
	 * Method to add user's fund. For example because of selling shares.
	 * @param value the fund to add
	 */
	public static void addFund(Double value) {
		fund += value;
		Users.users.get(username).addFund(value);
	}
	
	/**
	 * Method to take away fund. For example because of buying shares.
	 * @param value the fund to take away
	 */
	public static void takeFund(Double value) {
		fund -= value;
		Users.users.get(username).takeFund(value);
	}
	
	/**
	 * Method to set the user's fund
	 * @param value the fund to be set
	 */
	public static void setFund(Double value) {
		fund = value;
		Users.users.get(username).setFund(value);
	}
	
	/**
	 * This method should be called after user logged out
	 * It will clear all the user data
	 */
	public static void clearData() {
		username = "";
		shares = new HashMap<String, Integer>();
		firstFourTriggered = false;
		currentMainTab = 1;
		currentCompanyStockInfoTab = 1;
		month = 1;
		year = 2011;
		helpNum = 0;
		companySearchPick = "";
		from_company_info = null;
		from_objective = null;
		from_help = null;
		currentObj = null;
		objectiveList.clear();
		objectiveNumber = 1;
		MainPageActivity.first_time = true;
	}
	
	/**
	 * Method to check whether a company exists
	 * @param cName the company name
	 * @return true if company exists; false otherwise
	 */
	public static boolean doesCompanyExist(String cName) {
		if (shares.containsKey(cName)) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Method to add share into the our local data
	 * @param companyName the company name
	 * @param ss the object StockShares
	 */
	public static void addShare(String companyName, Integer share) {
		if (shares.containsKey(companyName)) {
			shares.put(companyName, share);
		} else {
			shares.put(companyName, share);
			companyNames.add(companyName);
		}
		
		Users.users.get(username).addShare(companyName, share);
	}
	
	/**
	 * Method to remove the company where user has shares at.
	 * Should be called when user sells all owned shares at that company.
	 * @param companyName the company to get removed from user's shares list
	 * @return true if successful; false otherwise
	 */
	public static boolean removeCompanyShare(String companyName) {
		if (shares.containsKey(companyName)) {
			shares.remove(companyName);
			companyNames.remove(companyName);
			Users.users.get(username).removeCompanyShare(companyName);
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Method to get the number of stock shares
	 * @param companyName the company which has your shares
	 * @return the number of shares that user has in that company; 0 otherwise
	 */
	public static Integer getShare(String companyName) {
		return shares.get(companyName) == null ? 0 :
			shares.get(companyName);
		
	}
	
	/**
	 * Method to check whether a user is logged in
	 * @return true if user is logged in, false otherwise
	 */
	public static boolean isLoggedIn() {
		if (!username.equals(""))
			return true;
		else
			return false;
	}
	
	/**
	 * Method to get total shares owned
	 * @return the number of shares owned in total
	 */
	public static int getTotalSharesOwned() {
		int totalShare = 0;
		for (String cName : companyNames) {
			totalShare += shares.get(cName);
		}
		return totalShare;
	}
	
	/**
	 * Method to get total assets (total stock value + user's current fund)
	 * @return the total assets user has
	 */
	public static Double getTotalAssets() {
		Double totalAssets = getTotalStockValue();
		totalAssets += getFund();
		return totalAssets;
	}
	
	/**
	 * Method to get total stock value
	 * @return the total assets user has
	 */
	public static Double getTotalStockValue() {
		Double totalStockValue = 0.00;
		Integer share = 0;
		Double companyShareValue = 0.00;
		for (String cName : companyNames) {
			share = shares.get(cName);
			companyShareValue = Companies.getCompanyShareValue(cName);
			totalStockValue += share * companyShareValue;
		}
		return totalStockValue;
	}
	
	/**
	 * Method to get all the shares that user owns
	 * @return all the owned share by user
	 */
	public static HashMap<String, Integer> getAllShares() {
		return shares;
	}
	
	/**
	 * Method to get all the company names where user has shares in
	 * @return company names where user has shares in
	 */
	public static LinkedList<String> getCompanyNames() {
		return companyNames;
	}
}
